package com.qianniu.napi.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.qianniu.napi.admin.entity.*;
import com.qianniu.napi.admin.entity.penum.IotypeEnum;
import com.qianniu.napi.admin.entity.penum.JftypeEnum;
import com.qianniu.napi.admin.entity.penum.XftypeEnum;
import com.qianniu.napi.admin.mapper.OrderGoodsMapper;
import com.qianniu.napi.admin.mapper.OrderMapper;
import com.qianniu.napi.admin.service.*;
import com.qianniu.napi.common.config.Constants;
import com.qianniu.napi.common.util.*;
import org.jdom.JDOMException;
import org.redisson.api.RAtomicLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author chenxuebin
 * @since 2018-06-24
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private OrderGoodsMapper orderGoodsMapper;
    @Autowired
    private IRedisService redisService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IJifenService jifenService;
    @Autowired
    private IXnbiFlowService xnbiFlowService;
    @Autowired
    private IAccountFlowService accountFlowService;
    @Autowired
    private IMaccountFlowService maccountFlowService;

    public List<OrderGoods> getOrderGoodsPage(String uid, int pageSize, int pageIndex, int status) {

        Map<String, Object> map = new HashMap<String, Object>();
        Wrapper<Order> entity = new EntityWrapper<Order>().eq("uid", "uid").eq("state", 1);
        if (status != 99) {
            entity.eq("status", status);
            map.put("status", status);
        }
        int total = orderMapper.selectCount(entity);

        Page page = new Page(pageIndex, pageSize);

        page.setTotal(total);

        map.put("uid", uid);
        map.put("size", pageSize);
        map.put("skip", page.getOffset());

        List<OrderGoods> list = orderGoodsMapper.selectOrderGoodsList(map);
        return list;
    }

    public List<Order> getOrderPage(String uid, int pageSize, int pageIndex, int status) {

        Map<String, Object> map = new HashMap<String, Object>();
        Page<Order> page = new Page<Order>(pageIndex, pageSize);


        Wrapper<Order> entity = new EntityWrapper<Order>().eq("uid", "uid").eq("state", 1);
        if (status != 99) {
            entity.eq("status", status);
            map.put("status", status);
        }
        entity.orderBy("id", false);


        int total = orderMapper.selectCount(entity);

        page.setTotal(total);

        map.put("uid", uid);
        map.put("size", pageSize);
        map.put("skip", page.getOffset());

        List<Order> list = orderGoodsMapper.selectOrderList(map);
        return list;
    }

    public List<Order> getPTOrderGoodsPage(Long uid, int pageSize, int pageIndex, int status) {

        Page page = new Page(pageIndex, pageSize);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("uid", uid);
        if (status != 99) map.put("status", status);

        int total = orderMapper.selectPTOrderCount(map);
        page.setTotal(total);

        logger.info("page.getOffset()=" + page.getOffset());
        logger.info("page.getLimit()=" + page.getLimit());

        map.put("size", pageSize);
        map.put("skip", page.getOffset());

        List<Order> list = orderMapper.selectPTOrderPage(map);

        return list;
    }

    public List<Order> getPTOGoodsPage(Long uid, int pageSize, int pageIndex, int status) {

        Page page = new Page(pageIndex, pageSize);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("uid", uid);

        if (status != 99) map.put("status", status);
        logger.info("==============getPTOGoodsPage map=" + JSON.toJSONString(map));

        int total = orderMapper.selectPTOCount(map);
        page.setTotal(total);

        logger.info("page.getOffset()=" + page.getOffset());
        logger.info("page.getLimit()=" + page.getLimit());

        map.put("size", pageSize);
        map.put("skip", page.getOffset());
        List<Order> list = orderMapper.selectPTOPage(map);

        return list;
    }

    public List<Order> getHuodongPage(Long uid, int pageSize, int pageIndex, int status) {

        Page page = new Page(pageIndex, pageSize);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("uid", uid);
        map.put("is_deleted", -1);

        if (status != 99) map.put("status", status);
        logger.info("==============getPTOGoodsPage map=" + JSON.toJSONString(map));

        int total = orderMapper.selectHuodongCount(map);
        page.setTotal(total);

        logger.info("page.getOffset()=" + page.getOffset());
        logger.info("page.getLimit()=" + page.getLimit());

        map.put("size", pageSize);
        map.put("skip", page.getOffset());
        List<Order> list = orderMapper.selectHuodongPage(map);

        return list;
    }

    public List<Order> getOrdersBygid(Long gid, int pageSize, int pageIndex) {

        Page page = new Page(pageIndex, pageSize);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("gid", gid);

        logger.info("==============getOrdersPage map=" + JSON.toJSONString(map));

        int total = orderMapper.selectHuodongCount(map);
        page.setTotal(total);

        logger.info("page.getOffset()=" + page.getOffset());
        logger.info("page.getLimit()=" + page.getLimit());

        map.put("size", pageSize);
        map.put("skip", page.getOffset());
        List<Order> list = orderMapper.selectOrdersBygid(map);

        return list;
    }

    public Double getOrderMoneyCountbyMonth(Long sid, String month) {

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("sid", sid);
        map.put("month", month);

        Double money = orderMapper.getOrderMoneyCountbyMonth(map);
        return money;
    }

    public int getHdCanyushu(Long sid) {

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("sid", sid);

        int shu = orderMapper.getHdCanyushu(map);
        return shu;
    }

    public Account initAccount() {

        BigDecimal zero = new BigDecimal(0);

        Account act = new Account();
        act.setUid(ObjectUtil.getUid());
        act.setMid(ObjectUtil.getMid());
        act.setMpid(ObjectUtil.getMpid());
        act.setCreatetime(new Date());
        act.setVersion(1l);
        act.setState(1);

        User user = redisService.getUser();
        act.setNickname(user != null ? user.getNickName() : null);
        act.setHeadimg(user != null ? user.getAvatarPic() : null);
        act.setPhone(user != null ? user.getPhone() : null);

        act.setTotal(zero);
        act.setAmount(zero);
        act.setUnuseAmount(zero);
        act.setFanli(zero);
        act.setFanliing(zero);
        act.setFreeze(zero);
        act.setChargeAmount(zero);
        act.setLjxiaofei(zero);
        act.setMamount(zero);
        act.setWithdraw(zero);
        act.insert();
        return act;
    }

    public Jifen initJifen() {

        BigDecimal zero = new BigDecimal(0);

        Jifen act = new Jifen();
        act.setUid(ObjectUtil.getUid());
        act.setMid(ObjectUtil.getMid());
        act.setMpid(ObjectUtil.getMpid());

        act.setCreatetime(new Date());
        act.setVersion(1l);
        act.setTotal(zero);
        act.setFanliing(zero);
        act.setState(1);
        act.insert();
        return act;
    }

    public Jifen initJifen(Long uid, Long mid, Long mpid) {

        BigDecimal zero = new BigDecimal(0);

        Jifen act = new Jifen();
        act.setUid(uid);
        act.setMid(mid);
        act.setMpid(mpid);

        act.setCreatetime(new Date());
        act.setVersion(1l);
        act.setTotal(zero);
        act.setFanliing(zero);
        act.setState(1);
        act.insert();
        return act;
    }

    public Xnbi initXnbi() {

        BigDecimal zero = new BigDecimal(0);

        Xnbi act = new Xnbi();
        act.setUid(ObjectUtil.getUid());
        act.setMid(ObjectUtil.getMid());
        act.setMpid(ObjectUtil.getMpid());

        act.setCreatetime(new Date());
        act.setVersion(1l);
        act.setTotal(zero);
        act.setFanliing(zero);
        act.setState(1);
        act.insert();
        return act;
    }

    public Maccount initMaccount() {

        BigDecimal zero = new BigDecimal(0);

        Maccount act = new Maccount();//初始化Maccount()
        act.setUid(ObjectUtil.getUid());
        act.setMid(ObjectUtil.getMid());
        act.setCreatetime(new Date());
        act.setVersion(1l);
        act.setState(1);

        act.setTotal(zero);
        act.setAmount(zero);
        act.setSaleAmount(zero);
        act.setMamount(zero);
        act.setUnuseAmount(zero);
        act.setFanliing(zero);
        act.setJifen(zero);
        act.setFreeze(zero);
        act.setChargeAmount(zero);
        act.setWithdraw(zero);
        act.setConsume(zero);
        // sms
        act.setSmsmout(new BigDecimal("80"));
        act.setSmsmoutTotal(new BigDecimal("80"));
        act.setSmsprice(new BigDecimal("0.08"));
        act.setSmstotal(1000);
        act.insert();

        logger.debug("========initMaccount=" + JSON.toJSONString(act));
        return act;
    }

    // 处理实际付款额>0 逻辑
    public SortedMap<String, Object> getPaymap(Order order, Boolean isRepay, String title) {
        String prepay_id = null;
        SortedMap<String, Object> smap = new TreeMap<String, Object>();
        long mid = order.getMid();
        String uid = order.getUid().toString();
        String appid = ObjectUtil.getAppid();
        MerchantApp mapp = redisService.getMApp();
        Boolean newRepay = Strings.isNullOrEmpty(order.getPrepayid());
        logger.debug("============================mapp="+JSON.toJSONString(mapp));
        //时间戳
        String nonce_str = StringUtil.getGUID().substring(0, 16);
        //订单编号
        String orderNo = order.getOrderNo();
        User user = redisService.getUser();
        if (!isRepay || Strings.isNullOrEmpty(order.getPrepayid())) {
            // 生成支付相关字段
            // 1.得到openid
            String openid = user.getOpenid();// 替换redis

            logger.debug(">>>order.getRealpay()=" + order.getRealpay());
            if (order.getRealpay() == null) order.setRealpay(new BigDecimal(0));

            BigDecimal totalfee = order.getRealpay().multiply(new BigDecimal("100"));

            //得到小程序传过来的价格，注意这里的价格必须为整数，1代表1分，所以传过来的值必须*100；
            int fee = totalfee.intValue();

            if (Strings.isNullOrEmpty(title)) title = "在线支付购买";//订单标题

            // *******  逻辑待完善 ********
//        if (order.getId() > 0 && order.getOrderType()==0) {
//            OrderGoods og = orderGoodsService.selectOne(new EntityWrapper<OrderGoods>().eq("oid", order.getId()));
//            title = "在线支付" + og.getGoodsName();
//        }else if(order.getOrderType()!=null && order.getOrderType()==1){
//            title = "在线支付" + order.getGoodsName();
//        }

            SortedMap<String, Object> params = new TreeMap<String, Object>();

            String expireTime = DateUtil.getOrderExpireTime(30 * 60 * 1000l);// 半个小时自动失效
            if (order.getGtype() == 5) {
                expireTime = DateUtil.getOrderExpireTime(5 * 60 * 1000l);
            }
            //新增服务商模式支付
            if(!Strings.isNullOrEmpty(mapp.getServappid())&&!Strings.isNullOrEmpty(mapp.getServmchid())){
                params.put("appid", mapp.getServappid());
                params.put("mch_id", mapp.getServmchid());
                params.put("openid", "");//openid

                params.put("sub_appid", appid);
                params.put("sub_mch_id", mapp.getMchid());
                params.put("sub_openid", openid);//openid

            } else {
                params.put("appid", appid);
                params.put("mch_id", mapp.getMchid());
                params.put("openid", openid);//openid
            }

            params.put("nonce_str", nonce_str);//时间戳
            params.put("body", title);//支付主体
            params.put("out_trade_no", orderNo);//编号
            params.put("total_fee", fee);//价格
            //params.put("spbill_create_ip", getIp2(request));这里之前加了ip，但是总是获取sign失败，原因不明，之后就注释掉了
            //params.put("spbill_create_ip", req.getRemoteAddr()); //这里之前加了ip，但是总是获取sign失败，原因不明，之后就注释掉了
            String notifyUrl = Constants.ROOT_URL + "/pay/notify";
            logger.debug("==========notifyUrl=" + notifyUrl);
            params.put("notify_url", notifyUrl); //支付返回地址，不用纠结这个东西，我就是随便写了一个接口，内容什么都没有
            params.put("trade_type", "JSAPI");//这个api有，固定的
            if (!isRepay) params.put("time_expire", expireTime);

            //获取sign
            logger.debug("-------------------------------------11-params=" + params);
            String sign = PayCommonUtil.createSign("UTF-8", params, mapp.getPaykey());//最后这个是自己设置的32位密钥
            params.put("sign", sign);

            //转成XML
            logger.debug("-------------------------------------22-params=" + params);
            String requestXML = PayCommonUtil.getRequestXml(params);

            //得到含有prepay_id的XML
            String resXml = HttpUtil.postData(Constants.WX_URL_UNIFIEDORDER, requestXML);
            logger.debug("-------------------------------------requestXML");
            logger.debug(resXml);

            //解析XML存入Map
            Map map = null;
            try {
                map = XMLUtil.doXMLParse(resXml);
            } catch (JDOMException | IOException e) {
                logger.error(">>>doXMLParse error", e);
                smap.put("code", 1);
                smap.put("msg", "支付异常");
                return smap;
            }
            if (map == null) {
                smap.put("code", 1);
                smap.put("msg", "请求异常");
                return smap;
            }
            if (map.get("result_code").equals("FAIL")) {
                smap.put("code", 1);
                smap.put("msg", map.get("err_code_des"));
                return smap;
            }
            //String return_code = (String) map.get("return_code");
            //得到prepay_id
            prepay_id = (String) map.get("prepay_id");
        } else {
            prepay_id = order.getPrepayid();
        }

        Order uorder = new Order();
        uorder.setPrepayid(prepay_id);
        uorder.setId(order.getId());
        uorder.setId(order.getId());
        uorder.updateById();

        smap.put("appId", appid);//！！！注意，这里是appId,上面是appid，真怀疑写这个东西的人。。。
        smap.put("nonceStr", nonce_str);//时间戳
        smap.put("package", "prepay_id=" + prepay_id);//必须把package写成 "prepay_id="+prepay_id这种形式
        smap.put("signType", "MD5");//paySign加密
        smap.put("timeStamp", (System.currentTimeMillis() / 1000) + "");

        //得到paySign
        String paySign = PayCommonUtil.createSign("UTF-8", smap, mapp.getPaykey());
        smap.put("paySign", paySign);
        smap.put("oid", order.getId());//paySign加密

        if (!isRepay|| Strings.isNullOrEmpty(order.getPrepayid())) {
            // 订单消费产生流水
            BigDecimal zero = new BigDecimal(0);

            // 独立支付商户，用户实际付款额入账
            // 非独立支付商户，以后再支持完善---待完善
            BigDecimal ambc = zero;
            BigDecimal mkbc = zero;
            boolean updateflag = false;

            // 先处理用户，再处理商户
            // 更新积分信息
            JifenFlow jf = null;
            if (order.getJifen() != null && order.getJifen().doubleValue() > 0) {
                // 使用积分后，本次购买商品不再赠送积分
                jf = new JifenFlow();

                // *******  待更新  *******
                jf.setNum(order.getJifen());
                jf.setSn(order.getOrderNo());// 抵扣积分时 = 订单号
                jf.setIotype(IotypeEnum.output.getVal());//积分消费
                jf.setJftype(JftypeEnum.dikou.getVal());//积分消费
                jf.setCreatetime(new Date());
                jf.setUid(ObjectUtil.getUid());
                jf.setMid(mid);
                jf.setMpid(order.getMpid());
                jf.setRemark("消费抵扣积分");
                jf.setIsConfirm(-1);
                jf.setState(1);
                updateflag = jf.insert();
                logger.debug(">>> JifenFlow insert=" + updateflag);
                // 支付完成更新总积分
            }
            XnbiFlow xflow = null;
            if (order.getBie() != null && order.getBie().doubleValue() > 0) {
                // 使用虚拟币后，本次购买商品不再赠送积分
                xflow = new XnbiFlow();

                // *******  待更新  *******
                xflow.setNum(order.getJifen());
                xflow.setSn(order.getOrderNo());// 抵扣积分时 = 订单号
                xflow.setIotype(IotypeEnum.output.getVal());//积分消费
                xflow.setJftype(JftypeEnum.dikou.getVal());//积分消费
                xflow.setCreatetime(new Date());
                xflow.setUid(ObjectUtil.getUid());
                xflow.setMid(mid);
                xflow.setMpid(order.getMpid());
                xflow.setRemark("消费抵扣虚拟币");
                xflow.setSn(order.getOrderNo());
                xflow.setIsConfirm(-1);
                xflow.setState(1);
                updateflag = xflow.insert();
                logger.debug(">>> JifenFlow insert=" + updateflag);
                // 支付完成更新总积分
            }

            Account act = accountService.selectOne(new EntityWrapper<Account>().eq("uid", uid));
            if (act == null) act = accountService.initAccount(order.getUid(), mid, order.getMpid());

            if (order.getDeduction() != null && order.getDeduction().doubleValue() > 0) {
                if (act.getAmount().doubleValue() >= order.getDeduction().doubleValue()) {
                    ambc = order.getDeduction();
                } else if (act.getAmount().doubleValue() <= 0) {
                    mkbc = order.getDeduction();
                } else {
                    ambc = act.getAmount();//真实会员余额
                    mkbc = order.getDeduction().subtract(act.getAmount());//赠送余额
                }
            }

            AccountFlow af = new AccountFlow();
            af.setAmount(ambc);
            af.setDikou(mkbc.add(order.getDiscount()));// 总营销金额 130
            af.setRealpay(order.getRealpay());// 总价200 实付100
            af.setTotal(order.getRealpay().add(order.getDeduction()).add(order.getDiscount()));

            af.setSn(order.getOrderNo());
            af.setIotype(IotypeEnum.output.getVal());// 个人账户出账

            logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>order.getType() =" + order.getType());
            if (order.getXftype().intValue() == XftypeEnum.jyajin.getVal()) {
                logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>jyajin");
                af.setXftype(XftypeEnum.jyajin.getVal());//交押金
                af.setIotype(IotypeEnum.input.getVal());//个人账户出账

            } else if (order.getXftype().intValue() == XftypeEnum.maidan.getVal()) {
                logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>maidan");
                af.setXftype(XftypeEnum.maidan.getVal());//线下付款买单

            } else if (order.getXftype().intValue() == XftypeEnum.paidan.getVal()) {
                logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>maidan");
                af.setXftype(XftypeEnum.paidan.getVal());//线下付款买单

            } else {
                logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>buy");
                af.setXftype(XftypeEnum.buy.getVal());//个人消费
            }

            af.setNickname(user != null ? user.getNickName() : null);
            af.setHeadimg(user != null ? user.getAvatarPic() : null);
            af.setPhone(user != null ? user.getPhone() : null);

            af.setIsConfirm(-1);
            af.setState(1);

            af.setTradetime(new Date());
            af.setCreatetime(af.getTradetime());
            af.setRemark(title);
            af.setUid(order.getUid());
            af.setMid(mid);
            af.setMpid(order.getMpid());

            af.setLasttotal(act.getTotal());
            af.setLastamount(act.getAmount());
            af.insert();

            // 更新商户信息
            mkbc = mkbc.add(order.getDiscount());// 总营销金额130
            MaccountFlow maf = new MaccountFlow();

            maf.setAmount(order.getRealpay());// 实付100剩余20在一次充值时已更新
            maf.setMamount(mkbc);// 各种抵扣额度=商家的营销费用=总营销金额130

            maf.setUid(order.getUid());
            maf.setMid(order.getMid());
            maf.setMpid(order.getMpid());
            maf.setCreatetime(new Date());
            maf.setTradetime(new Date());
            maf.setState(1);//未确认
            maf.setIsConfirm(-1);//未确认

            maf.setIotype(IotypeEnum.input.getVal());//1:入账账
            maf.setXftype((order.getXftype() == XftypeEnum.jyajin.getVal() || order.getXftype() == XftypeEnum.maidan.getVal())
                    ? XftypeEnum.pshoukuan.getVal() : XftypeEnum.sell.getVal());//1:平台收款

            maf.setRemark(title);
            maf.setSn(orderNo);
            maf.insert();
        }

        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>smap="+JSON.toJSONString(smap));
        return smap;
    }

    // 处理实际付款额>0并且重新支付的逻辑
    public SortedMap<String, Object> getRepaymap(Order order, String title, String oldOrderNo) {
        String prepay_id = null;
        SortedMap<String, Object> smap = new TreeMap<String, Object>();
        long mid = order.getMid();
        String uid = order.getUid().toString();
        String appid = ObjectUtil.getAppid();
        MerchantApp mapp = redisService.getMApp();
        Boolean newRepay = Strings.isNullOrEmpty(order.getPrepayid());

        //时间戳
        String nonce_str = StringUtil.getGUID().substring(0, 16);
        //订单编号
        String orderNo = order.getOrderNo();
        User user = redisService.getUser();

        // 生成支付相关字段
        // 1.得到openid
        String openid = user.getOpenid();// 替换redis

        logger.debug(">>>order.getRealpay()=" + order.getRealpay());
        if (order.getRealpay() == null) order.setRealpay(new BigDecimal(0));

        BigDecimal totalfee = order.getRealpay().multiply(new BigDecimal("100"));

        //得到小程序传过来的价格，注意这里的价格必须为整数，1代表1分，所以传过来的值必须*100；
        int fee = totalfee.intValue();

        if (Strings.isNullOrEmpty(title)) title = "在线支付购买";//订单标题

        // *******  逻辑待完善 ********
//        if (order.getId() > 0 && order.getOrderType()==0) {
//            OrderGoods og = orderGoodsService.selectOne(new EntityWrapper<OrderGoods>().eq("oid", order.getId()));
//            title = "在线支付" + og.getGoodsName();
//        }else if(order.getOrderType()!=null && order.getOrderType()==1){
//            title = "在线支付" + order.getGoodsName();
//        }

        SortedMap<String, Object> params = new TreeMap<String, Object>();

        String expireTime = DateUtil.getOrderExpireTime(30 * 60 * 1000l);// 半个小时自动失效
        if (order.getGtype() == 5) {
            expireTime = DateUtil.getOrderExpireTime(5 * 60 * 1000l);
        }
        //新增服务商模式支付
        if(!Strings.isNullOrEmpty(mapp.getServappid())&&!Strings.isNullOrEmpty(mapp.getServmchid())){
            params.put("appid", mapp.getServappid());
            params.put("mch_id", mapp.getServmchid());
            params.put("openid", "");//openid

            params.put("sub_appid", appid);
            params.put("sub_mch_id", mapp.getMchid());
            params.put("sub_openid", openid);//openid

        } else {
            params.put("appid", appid);
            params.put("mch_id", mapp.getMchid());
            params.put("openid", openid);//openid
        }
        params.put("nonce_str", nonce_str);//时间戳
        params.put("body", title);//支付主体
        params.put("out_trade_no", orderNo);//编号
        params.put("total_fee", fee);//价格
        //params.put("spbill_create_ip", getIp2(request));这里之前加了ip，但是总是获取sign失败，原因不明，之后就注释掉了
        //params.put("spbill_create_ip", req.getRemoteAddr()); //这里之前加了ip，但是总是获取sign失败，原因不明，之后就注释掉了
        String notifyUrl = Constants.ROOT_URL + "/pay/notify";
        logger.debug("==========notifyUrl=" + notifyUrl);
        params.put("notify_url", notifyUrl); //支付返回地址，不用纠结这个东西，我就是随便写了一个接口，内容什么都没有
        params.put("trade_type", "JSAPI");//这个api有，固定的
        params.put("time_expire", expireTime);

        //获取sign
        logger.debug("-------------------------------------11-params=" + params);
        String sign = PayCommonUtil.createSign("UTF-8", params, mapp.getPaykey());//最后这个是自己设置的32位密钥
        params.put("sign", sign);

        //转成XML
        logger.debug("-------------------------------------22-params=" + params);
        String requestXML = PayCommonUtil.getRequestXml(params);

        //得到含有prepay_id的XML
        String resXml = HttpUtil.postData(Constants.WX_URL_UNIFIEDORDER, requestXML);
        logger.debug("-------------------------------------requestXML");
        logger.debug(resXml);

        //解析XML存入Map
        Map map = null;
        try {
            map = XMLUtil.doXMLParse(resXml);
        } catch (JDOMException | IOException e) {
            logger.error(">>>doXMLParse error", e);
            smap.put("code", 1);
            smap.put("msg", "支付异常");
            return smap;
        }
        if (map == null) {
            smap.put("code", 1);
            smap.put("msg", "请求异常");
            return smap;
        }
        if (map.get("result_code").equals("FAIL")) {
            smap.put("code", 1);
            smap.put("msg", map.get("err_code_des"));
            return smap;
        }
        //String return_code = (String) map.get("return_code");
        //得到prepay_id
        prepay_id = (String) map.get("prepay_id");

        Order uorder = new Order();
        uorder.setPrepayid(prepay_id);
        uorder.setId(order.getId());
        uorder.setId(order.getId());
        uorder.updateById();

        smap.put("appId", appid);//！！！注意，这里是appId,上面是appid，真怀疑写这个东西的人。。。
        smap.put("nonceStr", nonce_str);//时间戳
        smap.put("package", "prepay_id=" + prepay_id);//必须把package写成 "prepay_id="+prepay_id这种形式
        smap.put("signType", "MD5");//paySign加密
        smap.put("timeStamp", (System.currentTimeMillis() / 1000) + "");

        //得到paySign
        String paySign = PayCommonUtil.createSign("UTF-8", smap, mapp.getPaykey());
        smap.put("paySign", paySign);
        smap.put("oid", order.getId());//paySign加密

        // 订单消费产生流水
        BigDecimal zero = new BigDecimal(0);

        // 独立支付商户，用户实际付款额入账
        // 非独立支付商户，以后再支持完善---待完善
        BigDecimal ambc = zero;
        BigDecimal mkbc = zero;
        boolean updateflag = false;

        // 先处理用户，再处理商户
        // 更新积分信息
        JifenFlow jf = null;
        if (order.getJifen() != null && order.getJifen().doubleValue() > 0) {
            // 使用积分后，本次购买商品不再赠送积分
            jf = new JifenFlow();

            // *******  待更新  *******
            jf.setNum(order.getJifen());
            jf.setSn(order.getOrderNo());// 抵扣积分时 = 订单号
            jf.setIotype(IotypeEnum.output.getVal());//积分消费
            jf.setJftype(JftypeEnum.dikou.getVal());//积分消费
            jf.setCreatetime(new Date());
            jf.setUid(ObjectUtil.getUid());
            jf.setMid(mid);
            jf.setMpid(order.getMpid());
            jf.setRemark("消费抵扣积分");
            jf.setIsConfirm(-1);
            jf.setState(1);
            updateflag = jf.insert();
            logger.debug(">>> JifenFlow insert=" + updateflag);
            // 支付完成更新总积分
        }
        XnbiFlow xflow = null;
        if (order.getBie() != null && order.getBie().doubleValue() > 0) {
            // 使用虚拟币后，本次购买商品不再赠送积分
            xflow = new XnbiFlow();

            // *******  待更新  *******
            xflow.setNum(order.getJifen());
            xflow.setSn(order.getOrderNo());// 抵扣积分时 = 订单号
            xflow.setIotype(IotypeEnum.output.getVal());//积分消费
            xflow.setJftype(JftypeEnum.dikou.getVal());//积分消费
            xflow.setCreatetime(new Date());
            xflow.setUid(ObjectUtil.getUid());
            xflow.setMid(mid);
            xflow.setMpid(order.getMpid());
            xflow.setRemark("消费抵扣虚拟币");
            xflow.setSn(order.getOrderNo());
            xflow.setIsConfirm(-1);
            xflow.setState(1);
            updateflag = xflow.insert();
            logger.debug(">>> JifenFlow insert=" + updateflag);
            // 支付完成更新总积分
        }

        Account act = accountService.selectOne(new EntityWrapper<Account>().eq("uid", uid));
        if (act == null) act = accountService.initAccount(order.getUid(), mid, order.getMpid());

        if (order.getDeduction() != null && order.getDeduction().doubleValue() > 0) {
            if (act.getAmount().doubleValue() >= order.getDeduction().doubleValue()) {
                ambc = order.getDeduction();
            } else if (act.getAmount().doubleValue() <= 0) {
                mkbc = order.getDeduction();
            } else {
                ambc = act.getAmount();//真实会员余额
                mkbc = order.getDeduction().subtract(act.getAmount());//赠送余额
            }
        }

        AccountFlow af = new AccountFlow();
        af.setAmount(ambc);
        af.setDikou(mkbc.add(order.getDiscount()));// 总营销金额 130
        af.setRealpay(order.getRealpay());// 总价200 实付100
        af.setTotal(order.getRealpay().add(order.getDeduction()).add(order.getDiscount()));

        af.setSn(order.getOrderNo());
        af.setIotype(IotypeEnum.output.getVal());// 个人账户出账

        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>order.getType() =" + order.getType());
        if (order.getXftype().intValue() == XftypeEnum.jyajin.getVal()) {
            logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>jyajin");
            af.setXftype(XftypeEnum.jyajin.getVal());//交押金
            af.setIotype(IotypeEnum.input.getVal());//个人账户出账

        } else if (order.getXftype().intValue() == XftypeEnum.maidan.getVal()) {
            logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>maidan");
            af.setXftype(XftypeEnum.maidan.getVal());//线下付款买单

        } else if (order.getXftype().intValue() == XftypeEnum.paidan.getVal()) {
            logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>maidan");
            af.setXftype(XftypeEnum.paidan.getVal());//线下付款买单

        } else {
            logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>buy");
            af.setXftype(XftypeEnum.buy.getVal());//个人消费
        }

        af.setNickname(user != null ? user.getNickName() : null);
        af.setHeadimg(user != null ? user.getAvatarPic() : null);
        af.setPhone(user != null ? user.getPhone() : null);

        af.setIsConfirm(-1);
        af.setState(1);

        af.setTradetime(new Date());
        af.setCreatetime(af.getTradetime());
        af.setRemark(title);
        af.setUid(order.getUid());
        af.setMid(mid);
        af.setMpid(order.getMpid());

        af.setLasttotal(act.getTotal());
        af.setLastamount(act.getAmount());
        af.insert();

        // 更新商户信息
        mkbc = mkbc.add(order.getDiscount());// 总营销金额130
        MaccountFlow maf = new MaccountFlow();

        maf.setAmount(order.getRealpay());// 实付100剩余20在一次充值时已更新
        maf.setMamount(mkbc);// 各种抵扣额度=商家的营销费用=总营销金额130

        maf.setUid(order.getUid());
        maf.setMid(order.getMid());
        maf.setMpid(order.getMpid());
        maf.setCreatetime(new Date());
        maf.setTradetime(new Date());
        maf.setState(1);//未确认
        maf.setIsConfirm(-1);//未确认

        maf.setIotype(IotypeEnum.input.getVal());//1:入账账
        maf.setXftype((order.getXftype() == XftypeEnum.jyajin.getVal() || order.getXftype() == XftypeEnum.maidan.getVal())
                ? XftypeEnum.pshoukuan.getVal() : XftypeEnum.sell.getVal());//1:平台收款

        maf.setRemark(title);
        maf.setSn(orderNo);
        maf.insert();

        //删除废弃的流水记录
        jifenService.delete(new EntityWrapper<Jifen>().eq("sn",oldOrderNo));
        xnbiFlowService.delete(new EntityWrapper<XnbiFlow>().eq("sn",oldOrderNo));
        accountFlowService.delete(new EntityWrapper<AccountFlow>().eq("sn",oldOrderNo));
        maccountFlowService.delete(new EntityWrapper<MaccountFlow>().eq("sn",oldOrderNo));

        logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>smap="+JSON.toJSONString(smap));
        return smap;
    }

    public Long orderFanuid(String oriscene) {
        if(Strings.isNullOrEmpty(oriscene)) return null;
        Long fanuid = null;
        String[] oris = oriscene.split("@");
        if (oris.length >= 1) {
            String scene = oris[0].replace("null", "");
            logger.debug("-----------------------------------------------start to orderFanuid scene=" + scene);
            if (!Strings.isNullOrEmpty(scene) && !scene.equals("null")) {
                // scene format //uid+page+act+ywid
                //uid.toString() + "_jfzhifu_Q_" + ywid;
                try {
                    fanuid = Long.parseLong(scene.split("_")[0]);
                } catch (Exception e) {
                    logger.error("orderFanuid Long.parseLong fanuid error", e);
                }
            }
        }

        if (oris.length >= 2) {
            //9c7d2de6-d921-3cfd-f14d-3fcd89f270d8_miaosha_button_31005
            //9c7d2de6-d921-3cfd-f14d-3fcd89f270d8
            String ori = oris[1].replace("null", "");
            logger.debug("----------------------------------------------start to orderFanuid ori=" + ori);
            String guid = ori.split("_")[0];
            User user = userService.selectOne(new EntityWrapper<User>().setSqlSelect("id,guid").eq("guid", guid));
            if (user != null) fanuid = user.getId();
        }
        return fanuid;
    }

    public String getShortno(Long mpid) {
        MerchantConfig mconfig = redisService.getMconfig(mpid);
        if (mconfig.getShortno() != null && mconfig.getShortno() == 1) {
            String shortno = DateUtil.getShortToday().substring(4);
            String rkey = Constants.MERCHANT_ORDER_COUNT + mpid + "_" + shortno;
//            RAtomicLong aint = redisService.getRAtomicLong(rkey);
//            if (aint == null||!aint.isExists()) {
//                int cout = orderMapper.selectCount(new EntityWrapper<Order>().eq("mpid", mpid)
//                        .like("order_no", DateUtil.getShortToday()));
//                aint.set(cout);
//            }
            int cout = orderMapper.selectCount(new EntityWrapper<Order>().eq("mpid", mpid)
                        .like("order_no", DateUtil.getShortToday()))+1;
            if (shortno.indexOf("0") == 0) shortno = shortno.substring(1);
//            shortno = shortno + aint.incrementAndGet();
            shortno = shortno + cout;
//            redisService.set(rkey, aint, 24, TimeUnit.HOURS);
            return shortno;
        }
        return null;
    }

    public String getStoreShortno(Long mpid,Long sid) {

        String shortno = DateUtil.getShortToday().substring(4);
        String rkey = Constants.MERCHANT_ORDER_COUNT + mpid + "_" + sid + "_" + shortno;

        int cout = orderMapper.selectCount(new EntityWrapper<Order>().eq("sid", sid)
                    .like("order_no", DateUtil.getShortToday()))+1;
        if (shortno.indexOf("0") == 0) shortno = shortno.substring(1);

        shortno = shortno + cout;

        return shortno;
    }

}
